<template>
    <div class="report-spec">
        <div v-for="(flatSpecItem, index) in flatSpecList" :key="flatSpecItem.path" class="report-spec-block">
            <spec-item
                v-if="flatSpecItem.isShow"
                v-model="flatSpecList[index]"
                :disabled="refDisabled"
                :event-bus="eventBus"
            />
        </div>
    </div>
</template>

<script>
/**
 * @file SpecEditor fanxueliang
 * @author fanxueliang@qq.com
 */

import {defineComponent, watch, onMounted, unref, computed, ref} from 'vue';
import {useFlatSpecAttr} from '../hooks/useFlatSpecAttr';
import SpecItem from './SpecItemAttr.vue';
import {each, keys, set, isEmpty, isEqual, get, debounce, includes} from 'lodash-es';
import {componentUi} from '../utils/enum';
import mitt from 'mitt';

export default defineComponent({
    name: 'report-spec-editor',
    components: {
        SpecItem
    },
    props: {
        spec: {
            type: Array,
            required: true
        },
        regexRules: {
            type: Array,
            default: () => []
        },
        modelValue: {
            type: Array,
            default: () => []
        },
        disabled: Boolean,
        actionLinkList: {
            type: Array,
            default: () => []
        }
    },
    setup(props, {emit}) {
        const refDisabled = computed(() => props.disabled);
        const flatSpecList = ref([]);
        flatSpecList.value = useFlatSpecAttr(props.spec, props.regexRules, props.modelValue, props.actionLinkList);

        const eventBus = mitt();

        const composeSpec = (specModel, attrMap, spec) => {
            const specKeys = keys(specModel);
            const specData = {};

            each(specKeys, (specKey) => {
                const attrConfig = attrMap[specKey];
                if (!attrConfig) {
                    return;
                }
                const {path, component} = attrConfig;
                // 收集数据条件
                // 存在path, 值被修改过
                if (path && !isEqual(specModel[specKey], get(spec, path))) {
                    if (specModel[specKey] !== null) {
                        set(specData, path, specModel[specKey]);
                    } else if (specModel[specKey] == null && component === componentUi.NumberInput) {
                        set(specData, path, -1);
                    } else if (
                        specModel[specKey] == null &&
                        includes(
                            [componentUi.CheckboxGroup, componentUi.RangeAdapter, componentUi.EnumValuesAdapter],
                            component
                        )
                    ) {
                        set(specData, path, []);
                    } else if (specModel[specKey] == null) {
                        set(specData, path, '');
                    }
                }
            });
            return specData;
        };

        const getDiffSpecModel = (val) => {
            const specModel = [];
            each(val, (item) => {
                const {specConfig = {}, spec} = item;
                const {attrMap, attrModel, extraAttrMap, extraAttrModel, rulesMap, rulesModel} = specConfig;
                const specData = {
                    path: item.path,
                    spec: {
                        ...composeSpec(attrModel, attrMap, spec),
                        ...composeSpec(extraAttrModel, extraAttrMap, spec),
                        ...composeSpec(rulesModel, rulesMap, spec)
                    }
                };
                // 过滤spec diff为空的节点
                if (!isEmpty(specData.spec)) {
                    specModel.push(specData);
                }
            });
            console.log(specModel);
            emit('update:modelValue', specModel);
        };
        const changeHandler = debounce(getDiffSpecModel, 500);
        watch(
            flatSpecList,
            (val) => {
                changeHandler(val);
            },
            {deep: true}
        );

        watch(
            () => ({spec: props.spec, modifySpec: props.modelValue}),
            (val) => {
                flatSpecList.value = useFlatSpecAttr(
                    props.spec,
                    props.regexRules,
                    props.modelValue,
                    props.actionLinkList
                );
            }
        );

        onMounted(() => {
            getDiffSpecModel(unref(flatSpecList));
        });

        return {
            eventBus,
            refDisabled,
            flatSpecList
        };
    }
});
</script>

<style lang="less" scoped>
@import '../css/lib.less';

.report-spec {
    padding: @vertical-spacing;
    background-color: @dls-color-gray-0;
    /deep/ *,
    /deep/ :after,
    /deep/ :before {
        box-sizing: border-box;
    }

    .report-spec-block {
        background-color: @dls-color-gray-2;
        margin-bottom: 20px;
    }
}
</style>
